package pers.vic.boot.console.system.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.vic.boot.base.model.BaseResponse;
import pers.vic.boot.base.service.BaseService;
import pers.vic.boot.console.system.mapper.SysRoleMapper;
import pers.vic.boot.console.system.mapper.SysUserMapper;
import pers.vic.boot.console.system.model.SysRole;
import pers.vic.boot.console.system.model.SysUser;
import pers.vic.boot.security.jwt.AuthorityInfo;
import pers.vic.boot.security.jwt.JwtService;
import pers.vic.boot.util.CommonUtils;
import pers.vic.boot.util.collections.CalcDiffCollection;
import pers.vic.boot.util.encrypt.PasswordUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 系统用户表 Service
 * 
 * @author Vic.xu
 */
@Service
public class SysUserService extends BaseService<SysUserMapper, SysUser> {

	@Resource
	private SysRoleMapper sysRoleMapper;

	@Resource
	private JwtService jwtService;

	/**
	 * 保存用户 特殊处理下新增的时候新增默认密码 为用户名
	 */
	@Override
	public int save(SysUser entity) {
		if (entity.getId() == null || entity.getId() <= 0) {
			entity.setPassword(PasswordUtils.entryptPassword(entity.getUsername()));
		}
		return super.save(entity);
	}

	/**
	 * 根据用户名获取用心
	 */
	public SysUser findUserByUsername(String username) {
		return mapper.findUserByUsername(username);
	}

	/**
	 * 判断用户名是否重复
	 */
	public boolean checkUsername(Integer id, String username) {
		return mapper.checkUsername(id, username);
	}

	/** 根据主键id查询对象 */
	@Override
	public SysUser findById(int id) {
		SysUser entity = mapper.findById(id);
		entity.setRoles(findUserRoles(id));
		return entity;
	}

	/**
	 * @description: 用户拥有的角色
	 * @author: Vic.xu
	 * @date: 2020年1月13日 上午9:40:21
	 * @param id user id
	 * @return roles
	 */
	private List<SysRole> findUserRoles(Integer id) {
		return sysRoleMapper.findUserRoles(id);
	}

	/**
	 * @description: 用户的权限
	 * @author: Vic.xu
	 * @date: 2020年1月13日 上午9:43:12
	 * @param id 用户id
	 * @return 权限列表
	 */
	private List<String> findUserPermissions(Integer id) {
		return sysRoleMapper.findUserPermissions(id);
	}

	/**
	 * 保存用户以及他对应的角色
	 * 
	 * @param entity user
	 * @param roleIds roleIds
	 */
	@Transactional
	public void save(SysUser entity, Integer[] roleIds) {
		save(entity);
		updateSysRoleRel(entity.getId(), roleIds);

	}

	/**
	 * @description: 更新用户和角色的关系
	 * @author: Vic.xu
	 * @date: 2020年1月13日 上午9:38:46
	 * @param userId  userId
	 * @param roles roles
	 */
	private void updateSysRoleRel(Integer userId, Integer[] roles) {
		if (userId == null) {
			return;
		}
		if (roles == null || roles.length == 0) {
			mapper.deleteUserRoleByUserId(userId);
			return;
		}
		// 用户的已经拥有的角色
		List<Integer> oldRoleIds = mapper.userRoleIds(userId);

		CalcDiffCollection<Integer> calc = CalcDiffCollection.instance(oldRoleIds,
				new ArrayList<>(Arrays.asList(roles)));

		List<Integer> needAdd = calc.getOnlyInNew();
		List<Integer> needDel = calc.getOnlyInOld();
		if (!needAdd.isEmpty()) {// 新增角色和菜单关联
			mapper.addUserRole(userId, needAdd);
		}
		if (!needDel.isEmpty()) {// 删除角色和菜单关联
			mapper.deleteUserRole(userId, needDel);
		}
	}

	@Override
	protected boolean hasAttachment() {
		return true;
	}

	/**
	 * 
	 * @description: 登陆操作
	 * @author: Vic.xu
	 * @date: 2020年1月9日 上午11:00:39
	 * @param username username
	 * @param password password
	 */
	public BaseResponse<String> login(String username, String password) {
		SysUser user = findUserByUsername(username);
		if (user == null) {
			return BaseResponse.error("不存在的用户");
		}
		if (!PasswordUtils.validatePassword(password, user.getPassword())) {
			return BaseResponse.error("密码错误");
		}
		String token = buildToken(user);
		return BaseResponse.success(token);
	}

	/**
	 * @description: 通过user构建token
	 * @author: Vic.xu
	 * @date: 2020年1月15日 上午9:25:53
	 * @param user user
	 * @return token
	 */
	public String buildToken(SysUser user) {
		if (user == null) {
			return null;
		}
		// 权限列表
		List<String> permission = findUserPermissions(user.getId());
		// 角色列表 这里的role name 等其他信息
		List<String> roles = CommonUtils.listFilter(findUserRoles(user.getId()), SysRole::getName);
		AuthorityInfo info = new AuthorityInfo(user.getId(), user.getUsername(), roles, permission);
		// 构建token并缓存
		return jwtService.buildTokenAndCache(info);
	}
}
